<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Polis</title>

    <!-- Google tag (gtag.js) -->
    <% if (gaTrackingId) { %>
      <script async src="https://www.googletagmanager.com/gtag/js?id=<%= gaTrackingId %>"></script>
      <script>
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());

        gtag('config', '<%= gaTrackingId %>');
      </script>
    <% } %>

    <!-- 100% privacy-first analytics -->
    <script data-collect-dnt="true" async src="https://scripts.simpleanalyticscdn.com/latest.js"></script>
    <noscript><img src="https://queue.simpleanalyticscdn.com/noscript.gif?collect-dnt=true" alt="" referrerpolicy="no-referrer-when-downgrade"/></noscript>

    <!-- REPLACE_THIS_WITH_FB_META_TAGS -->

    <% if (process.env.NODE_ENV === 'production') { %>
    <link rel="stylesheet" type="text/css" href="/css/polis.css"> <!-- proxy all CSS through server for respond.js -->
    <% } %>

    <script>
      window.userObject = {};

      window.preload = "REPLACE_THIS_WITH_PRELOAD_DATA";
      window.version = "<%= versionString %>";
    </script>
    <script src="https://cdn.jsdelivr.net/npm/jwt-decode@latest/build/jwt-decode.min.js"></script>

    <style>
      .displaynone {
        display: none;
      }
      .hidden {
        visibility: hidden;
      }
      .screen-reader-text {
        border: 0;
        clip: rect( 1px, 1px, 1px, 1px );
        clip-path: inset( 50% );
        height: 1px;
        margin: -1px;
        overflow: hidden;
        padding: 0;
        position: absolute;
        width: 1px;
        word-wrap: normal;
      }
    </style>

    <script> // Fire off this ajax first. it's slower than the other CDN delivered things.
      (function() {        
        function parseQueryParams(queryString) {
          const params = new URLSearchParams(queryString);
          return Object.fromEntries(params);
        }

        function getXid() {
          var params = parseQueryParams(window.location.search);
          return params.xid;
        }
        function get_x_profile_image_url() {
          var params = parseQueryParams(window.location.search);
          return params.x_profile_image_url;
        }
        function get_x_name() {
          var params = parseQueryParams(window.location.search);
          return params.x_name;
        }
        function get_domain_whitelist_override_key() {
          var params = parseQueryParams(window.location.search);
          return params.dwok;
        }
        function getUiLang() {
          var params = parseQueryParams(window.location.search);
          return params.ui_lang;
        }

        window.POLIS_DELPHI_ENABLED = null;

        function getOidcToken() {
          function _getOidcTokenFromStorage(storage) {
            if (!storage) return null;
            for (var i = 0; i < storage.length; i++) {
              var key = storage.key(i);
              if (
                key &&
                key.indexOf("<%= oidcCacheKeyPrefix %>") === 0 &&
                key.indexOf("<%= oidcCacheKeyIdTokenSuffix %>") !== key.length - "<%= oidcCacheKeyIdTokenSuffix %>".length
              ) {
                try {
                  var value = storage.getItem(key);
                  if (value) {
                    var parsed = JSON.parse(value);
                    // Check for expiry and access_token
                    if (
                      parsed &&
                      parsed &&
                      parsed.access_token &&
                      parsed.expires_at &&
                      parsed.expires_at > Math.floor(Date.now() / 1000)
                    ) {
                      return parsed.access_token;
                    }
                  }
                } catch (e) {
                  // Not valid JSON or other error, continue
                }
              }
            }
            return null;
          }

          var token = _getOidcTokenFromStorage(window.localStorage);
          if (!token) {
            token = _getOidcTokenFromStorage(window.sessionStorage);
          }
          return token;
        }

        function isOidcAuthenticated() {
          function _hasOidcInStorage(storage) {
            if (!storage) return false;
            for (var i = 0; i < storage.length; i++) {
              var key = storage.key(i);
              if (key && key.indexOf("<%= oidcCacheKeyPrefix %>") === 0) {
                try {
                  var value = storage.getItem(key);
                  if (value) {
                    var parsed = JSON.parse(value);
                    // Check for any valid token (access_token or id_token) that hasn't expired
                    if (parsed && (parsed.access_token || parsed.id_token)) {
                      // Check expiry if present
                      if (parsed.expires_at && parsed.expires_at <= Math.floor(Date.now() / 1000)) {
                        continue; // Token expired, keep looking
                      }
                      return true;
                    }
                  }
                } catch (e) {
                  // Not valid JSON or other error, continue
                }
              }
            }
            return false;
          }

          return _hasOidcInStorage(window.localStorage) || _hasOidcInStorage(window.sessionStorage);
        }

        try {
            let XPT__ = getOidcToken();
            window.POLIS_DELPHI_ENABLED = jwt_decode(XPT__)['<%= authNamespace %>delphi_enabled'];
          } catch (error) {
            console.error(error);
          }


        function getConversationIdFromPath() {
          var pathname = document.location.pathname;
          var match =
            pathname.match(/^\/([0-9][0-9A-Za-z]+)/) ||
            pathname.match(/^\/conversation\/([0-9][0-9A-Za-z]+)/) ||
            pathname.match(/^\/m\/([0-9][0-9A-Za-z]+)/) ||
            pathname.match(/^\/demo\/([0-9][0-9A-Za-z]+)/);
          if (match) {
            return match[match.length - 1];
          }
          return null;
        }

        function ajaxGet(url, success, fail) {
          var xmlhttp;
          xmlhttp = new XMLHttpRequest();
          xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == XMLHttpRequest.DONE ) {
              if(xmlhttp.status == 200){
                try {
                  var parsed = JSON.parse(xmlhttp.responseText);
                  success(parsed);
                } catch (e) {
                  console.error("[Index] Error parsing JSON response:", e);
                  fail(xmlhttp.status, "JSON parse error: " + e.message);
                }
              } else {
                console.error("[Index] AJAX request failed with status:", xmlhttp.status, "response:", xmlhttp.responseText);
                
                // Try to parse error response as JSON first, fallback to text
                var errorResponse = xmlhttp.responseText;
                try {
                  var parsedError = JSON.parse(xmlhttp.responseText);
                  // If it's a JSON error response, extract the error message
                  if (parsedError && (parsedError.error || parsedError.message)) {
                    errorResponse = parsedError.error || parsedError.message;
                  }
                } catch (e) {
                  // Keep original text response if JSON parsing fails
                  console.warn("[Index] Error response is not JSON, using as text");
                }
                
                fail(xmlhttp.status, errorResponse);
              }
            }
          }

          xmlhttp.open("GET", url, true);
          
          // Add JWT token to request if available
          try {
            var token = null;
            var conversationId = getConversationIdFromPath();
            if (conversationId) {
              var tokenKey = "participant_token_" + conversationId;
              if (window.localStorage) {
                token = window.localStorage.getItem(tokenKey);
              }
              if (!token && window.sessionStorage) {
                token = window.sessionStorage.getItem(tokenKey);
              }
            }
            if (!token) {
              token = getOidcToken();
            }
            if (token) {
              xmlhttp.setRequestHeader('Authorization', 'Bearer ' + token);
            }
          } catch (e) {
            console.error("[Index] Error adding JWT token to request:", e);
          }
          
          xmlhttp.send();
        }

        // bootstrap initial bulk ajax call.
        // we don't have promises until main bundle loads, so this is going to be a bit messy.
        var p = window.preload;

        function fixupConversation(c) {
          var t = c.translations
          if (t && t.length) {
            c.topic = t[0].topic;
            c.description = t[0].description;
          }
          return c;
        }

        function onPreloadOk(response) {
          var things = [
            {src:"nextComment", dst:"firstComment", cb:"firstCommentListener"},
            {src:"conversation", dst:"firstConv", cb:"firstConvListener", fn:fixupConversation},
            {src:"user", dst:"firstUser", cb:"firstUserListener"},
            {src:"ptpt", dst:"firstPtpt", cb:"firstPtptListener"},
            {src:"votes", dst:"firstVotesByMe", cb:"firstVotesByMeListener"},
            {src:"pca", dst:"firstMath", cb:"firstMathListener", JSON: true},
            {src:"famous", dst:"firstFamous", cb:"firstFamousListener"},
            {src:"acceptLanguage", dst:"acceptLanguage", cb:"acceptLanguageListener"},
          ];
          
          // Handle JWT token if present in response
          if (response && response.auth && response.auth.token) {
            // Store the token for later use
            try {
              var token = response.auth.token;
              var parts = token.split('.');
              if (parts.length === 3) {
                var payload = JSON.parse(atob(parts[1]));
                if (payload.conversation_id) {
                  var tokenKey = "participant_token_" + payload.conversation_id;
                   if (window.localStorage) {
                    window.localStorage.setItem(tokenKey, token);
                  } else if (window.sessionStorage) {
                    window.sessionStorage.setItem(tokenKey, token);
                  }
                } else {
                  console.warn("[Index] No conversation_id in JWT payload, not storing token.");
                }
              }
            } catch (e) {
              console.error("[Index] Failed to store JWT token:", e);
            }
          }
          
          for (var i = 0; i < things.length; i++) {
            var r = things[i], src = r.src, dst = r.dst, cb = r.cb;

            if (response) {
              // Handle JSON parsing more safely
              if (r.JSON) {
                try {
                  // If response[src] is already an object, use it directly
                  if (typeof response[src] === 'object') {
                    p[dst] = response[src];
                  } else if (typeof response[src] === 'string') {
                    p[dst] = JSON.parse(response[src]);
                  } else {
                    p[dst] = response[src];
                  }
                } catch (e) {
                  console.error("[Index] Error parsing JSON for", src, ":", e);
                  p[dst] = response[src]; // Use raw value as fallback
                }
              } else {
                p[dst] = response[src];
              }
            }

            if (r.fn) {
              p[dst] = r.fn(p[dst]);
            }

            // weird issue probably due to setting a prop named bgcolor on a global?
            // manually set the prop
            if (response && response[src] && response[src].bgcolor) {
              p[dst].bgcolor = response[src].bgcolor;
            }

            if (p[cb]) {
              p[cb](0, p[dst]);
            }
          }
        }

        function onPreloadFail(statusCode, failResponse) {
          console.error("[Index] onPreloadFail called with status:", statusCode, "response:", failResponse);
          var cbs = [
            "firstCommentListener",
            "firstConvListener",
            "firstUserListener",
            "firstPtptListener",
            "firstVotesByMeListener",
            "firstMathListener",
            "firstFamousListener",
            "acceptLanguageListener",
          ];
          for (var i = 0; i < cbs.length; i++) {
            if (p[cbs[i]]) {
              p[cbs[i]](1);
            }
          }
          if (statusCode === 403 && failResponse.match(/^polis_err_domain/)) {
            console.warn("[Index] Domain error detected, showing bad domain message");
            function updateDomainMessage() {
              var el = document.getElementById("badDomainMessage");
              if (el) {
                el.className = el.className.replace( /(?:^|\s)displaynone(?!\S)/g , '');
                document.getElementById("mainSpinner").className += " displaynone";
                clearInterval(updateDomainIntervalRef);
              }
            }
            var updateDomainIntervalRef = setInterval(updateDomainMessage, 100);
          }
        }

        var path = document.location.pathname;
        var conversation_id = getConversationIdFromPath();
        var shouldPreload = !!conversation_id;

        window.xsThresh = 600; // nexus 7

        window.getPtptoiLimitForWidth = function(w) {
          return w < window.xsThresh ? 25 : void 0;
        };

        var qp = [];
        if (conversation_id) {
          qp.push("conversation_id=" + conversation_id);
        }
        qp.push("pid=-1");

        var xid = getXid();
        if (typeof xid !== "undefined") {
          window.preload.xid = xid;
          qp.push("xid=" + encodeURIComponent(xid));
          console.log("[Index] Added xid to query params:", xid);
          
          // Check if user is also authenticated via OIDC
          if (isOidcAuthenticated()) {
            alert("Warning, you are currently signed-in to polis, but have opened a conversation with an XID token. To participate with an XID, please log out of your polis account.");
          }
        }
        var x_profile_image_url = get_x_profile_image_url();
        if (typeof x_profile_image_url !== "undefined") {
          window.preload.x_profile_image_url = x_profile_image_url;
          qp.push("x_profile_image_url=" + encodeURIComponent(x_profile_image_url));
        }
        var x_name = get_x_name();
        if (typeof x_name !== "undefined") {
          window.preload.x_name = x_name;
          qp.push("x_name=" + encodeURIComponent(x_name));
        }
        var dwok = get_domain_whitelist_override_key();
        if (typeof dwok !== "undefined") {
          qp.push("domain_whitelist_override_key=" + encodeURIComponent(dwok));
        }

        var ui_lang = getUiLang();
        if (ui_lang) {
          qp.push("lang=" + ui_lang);
          window.ui_lang = ui_lang;
        } else {
          qp.push("lang=acceptLang");
        }

        var qp = qp.join("&");
        qp = qp.length > 1 ? ("?" + qp) : "";
        
        var finalUrl = "/api/v3/participationInit" + qp;

        ajaxGet(finalUrl, onPreloadOk, onPreloadFail);

      }());
    </script>
  </head>
  <body class="clickDeselectsHull" style="margin:0; background-color: white;">

    <p id="mainSpinner" style="text-align:center; margin: auto; width:100%; display: none">
      <svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
        width="40px" height="40px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
      <path fill="rgba(0,0,0,0.5)" d="M43.935,25.145c0-10.318-8.364-18.683-18.683-18.683c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615c8.072,0,14.615,6.543,14.615,14.615H43.935z">
        <animateTransform attributeType="xml"
          attributeName="transform"
          type="rotate"
          from="0 25 25"
          to="360 25 25"
          dur="1.0s"
          repeatCount="indefinite"/>
        </path>
      </svg>
    </p>
    <p id="badDomainMessage" class="HeadingC displaynone" style="text-align:center; margin: 40px;">This conversation can't be viewed from this domain. Contact the creator of the conversation to find out where you can access it.</p>

    <script>
      if (window.top !== window) {
        document.getElementById("mainSpinner").classList.add("hidden");
      }

      if (window.ui_lang) {
        document.getElementsByTagName("body")[0].setAttribute("lang", ui_lang);
      }
    </script>
</body>
</html>
